package org.learn.simple.file.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.learn.simple.file.server.handlers.FileServerInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Objects;

/**
 * 服务器类
 * @author <a href="mailto:675464934@qq.com">Terrdi</a>
 * @date 2021/12/19
 * @since 1.8
 **/
public class FileServer implements AutoCloseable {
    private final static Logger logger = LoggerFactory.getLogger(FileServer.class);

    /**
     * 监听端口
     */
    private final static int PORT = 8088;

    public FileServer(String basePath, int port) {
        this.port = port;
        this.basePath = basePath;

        this.bossGroup = new NioEventLoopGroup(1);
        this.workerGroup = new NioEventLoopGroup();
    }

    public static void main(String[] args) {
        try (FileServer server = new FileServer("/Users/liuhanwei/Downloads", PORT)) {
            server.start();
        } catch (IOException | InterruptedException e) {
            logger.error("发生错误", e);
        }
    }


    /**
     * 接收请求的线程池
     */
    private EventLoopGroup bossGroup;

    /**
     * 处理请求的线程池
     */
    private EventLoopGroup workerGroup;

    /**
     * 监听的端口
     */
    private final int port;

    /**
     * 监听的路径
     */
    private final String basePath;

    @Override
    public void close() throws IOException {
        if (Objects.nonNull(this.workerGroup)) {
            this.workerGroup.shutdownGracefully();
        }
        if (Objects.nonNull(this.bossGroup)) {
            this.bossGroup.shutdownGracefully();
        }
    }

    public void start() throws IOException, InterruptedException {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(this.bossGroup, this.workerGroup).channel(NioServerSocketChannel.class)
                .childHandler(new FileServerInitializer(this.basePath));

        ChannelFuture channelFuture = serverBootstrap.bind(this.port).sync();

        channelFuture.addListener(future -> {
            logger.info("监听{}端口{}", this.port, future.isSuccess() ? "成功" : "失败");
        });

        channelFuture.channel().closeFuture().sync();
    }
}
